package com.iqiyi.pps.epg.core.service.record;

import com.alibaba.fastjson.JSONObject;
import com.iqiyi.pps.epg.api.model.web.query.TFilter;
import com.iqiyi.pps.epg.api.model.web.query.TPage;
import com.iqiyi.pps.epg.api.model.web.record.TRecordColData;
import com.iqiyi.pps.epg.api.model.web.record.TRecordColDataPage;
import com.iqiyi.pps.epg.core.dao.base.Page;
import com.iqiyi.pps.epg.core.dao.base.PropertyFilter;
import com.iqiyi.pps.epg.core.dao.channel.ChannelBaseDao;
import com.iqiyi.pps.epg.core.dao.record.RecordChannelDao;
import com.iqiyi.pps.epg.core.dao.record.RecordColDao;
import com.iqiyi.pps.epg.core.model.channel.ChannelBase;
import com.iqiyi.pps.epg.core.model.record.RecordChannel;
import com.iqiyi.pps.epg.core.model.record.RecordCol;
import com.iqiyi.pps.epg.core.utils.SqlUtil;
import com.iqiyi.pps.epg.core.utils.TransUtil;
import org.apache.commons.lang.StringUtils;
import org.hibernate.type.StringType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by wangle on 2018/4/10.
 */
@Service
@Transactional
public class RecordColServiceImpl implements RecordColService {
    private static final Logger logger = LoggerFactory.getLogger(RecordColServiceImpl.class);

    @Autowired
    private RecordColDao recordColDao;

    @Override
    public boolean save(String param) {
        logger.info("[RecordColServiceImpl][save][start][param={}]", param);
        try {
            RecordCol recordCol = JSONObject.parseObject(param, RecordCol.class);
            recordCol.setStatus(1);
            recordColDao.save(recordCol);
            logger.info("[RecordColServiceImpl][save][finish][param={}]", param);
            return true;
        } catch (Exception e) {
            logger.error("[RecordColServiceImpl][save][error][param={}][Exception={}]", param, e);
            return false;
        }
    }

    @Override
    public boolean update(String param) {
        logger.info("[RecordColServiceImpl][update][start][param={}]", param);
        try {
            logger.info("[RecordColServiceImpl][update][finish][param={}]", param);
            JSONObject json = JSONObject.parseObject(param);
            Long id = json.getLong("id");
            String colName = json.getString("colName");
            String channelName = json.getString("channelName");
            Long channelId = json.getLong("channelId");
            Long categoryId = json.getLong("categoryId");
            Integer hasAuth = json.getInteger("hasAuth");
            Integer hasPublic = json.getInteger("hasPublic");
            String opUser = json.getString("opUser");
            RecordCol recordCol = recordColDao.get(id);
            recordCol.setColName(colName);
            recordCol.setCategoryId(categoryId);
            recordCol.setChannelId(channelId);
            recordCol.setHasAuth(hasAuth);
            recordCol.setHasPublic(hasPublic);
            recordCol.setChannelName(channelName);
            recordColDao.save(recordCol);
            return true;
        } catch (Exception e) {
            logger.error("[RecordColServiceImpl][update][error][param={}][Exception={}]", param, e);
            return false;
        }
    }

    @Override
    public boolean update(RecordCol entity) {
        try{
            recordColDao.save(entity);
            return true;
        }catch(Exception e){
            logger.error("[RecordColServiceImpl][update][error][entity]");
            return false;
        }
    }

    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public TRecordColDataPage getRecordCol(TPage page, TFilter filter) {
        logger.info("[RecordColServiceImpl][getRecordCol][start][page={}][filter={}]", page, filter);
        try {
            List<PropertyFilter> filterList = TransUtil.builderFilterList(filter);
            Page<RecordCol> dbPage = TransUtil.buildPage(page);
            String hql = "select col.id,col.colName,col.channelId,col.hasAuth,col.hasPublic,col.categoryId,col.opUser,col.createTime, col.status, " +
                    "col.channelName from RecordCol as col where col.status != 0";
            String sql = buildWithPropertyFilter(hql, filterList);
            List<TRecordColData> resultList = null;
            if (dbPage.isAutoCount()) {
                List<Object> objects = recordColDao.find(sql);
                page.setTotalCount(objects.size());
                resultList = transToThriftList(objects);
            }
            TRecordColDataPage recordColDataPage = new TRecordColDataPage();
            recordColDataPage.setTPage(page);
            recordColDataPage.setResult(resultList);
            return recordColDataPage;
        } catch (Exception e) {
            logger.error("[RecordColServiceImpl][getRecordCol][error][page={}][filter={}][Exception={}]", page, filter, e);
            return null;
        }
    }

    public static String buildWithPropertyFilter(String hql,final List<PropertyFilter> filters) {
        StringBuilder sb = new StringBuilder(hql);
        for (PropertyFilter filter : filters) {
            if (!filter.hasMultiProperties()) { //只有一个属性需要比较的情况.
                sb.append(" and ");
                sb.append(filter.getPropertyName());
                sb.append(" ");
                sb.append(getSQLOperatorByFilterMatchType(filter.getMatchType()));
                sb.append(" '");
                if (filter.getMatchType() == PropertyFilter.MatchType.LIKE) {
                    sb.append("%" + filter.getMatchValue() + "%");
                } else {
                    sb.append(filter.getMatchValue());
                }
                sb.append("' ");
            } else {//包含多个属性需要比较的情况,进行or处理.
                sb.append(" and ( ");

                int i = 0;
                for (String param : filter.getPropertyNames()) {
                    if (i > 0) sb.append(" or ");
                    sb.append(param);
                    sb.append(" ");
                    sb.append(getSQLOperatorByFilterMatchType(filter.getMatchType()));
                    sb.append(" '");
                    if (filter.getMatchType() == PropertyFilter.MatchType.LIKE) {
                        sb.append("%" + filter.getMatchValue() + "%");
                    } else {
                        sb.append(filter.getMatchValue());
                    }
                    sb.append("' ");
                    i++;
                }
                sb.append(" ) ");
            }
        }
        return sb.toString();
    }


    private static String getSQLOperatorByFilterMatchType(PropertyFilter.MatchType matchType) {
        String operator = "";
        //根据MatchType构造criterion
        switch (matchType) {
            case EQ:
                operator = "=";
                break;
            case NEQ:
                operator = "!=";
                break;
            case LIKE:
                operator = "like";
                break;

            case LE:
                operator = "<=";
                break;
            case LT:
                operator = "<";
                break;
            case GE:
                operator = ">=";
                break;
            case GT:
                operator = ">";
        }
        return operator;
    }



    private List<TRecordColData> transToThriftList(List<Object> dataList) {
        List<TRecordColData> resultList = new ArrayList<>();
        for (Object obj : dataList) {
            Object[] data = (Object[]) obj;
            TRecordColData tRecordColData = transToThriftList(data);
            resultList.add(tRecordColData);
        }
        return resultList;
    }

    @Autowired
    private RecordChannelDao recordChannelDao;
    private SimpleDateFormat sdf = new SimpleDateFormat("yyyy:MM:dd HH:mm:ss");
    private TRecordColData transToThriftList(Object[] tempData) {
        TRecordColData thriftData = new TRecordColData();
        try {
            logger.info("[RecordColServiceImpl][getRecordCol][start][tempData={}]", tempData[0]);
            if (tempData[0]!=null) {
                thriftData.setId(Long.valueOf("" + tempData[0]));
            }
            if (tempData[9]!=null) {
                thriftData.setChannelName(String.valueOf("" + tempData[9]));
            }
            if (tempData[1]!=null) {
                thriftData.setColName(String.valueOf("" + tempData[1]));
            }
            if (tempData[2]!=null) {
                thriftData.setChannelId(Long.valueOf("" + tempData[2]));
            }
            if (tempData[3]!=null) {
                thriftData.setHasAuth(Integer.valueOf("" + tempData[3]));
            }
            if (tempData[4]!=null) {
                thriftData.setHasPublic(Integer.valueOf("" + tempData[4]));
            }
            if (tempData[5]!=null) {
                thriftData.setCategoryId(Long.valueOf("" + tempData[5]));
            }
            if (tempData[6]!=null) {
                thriftData.setOpUser(String.valueOf("" + tempData[6]));
            }
            if (tempData[7]!=null) {
                String format = sdf.format((Timestamp) tempData[7]);
                thriftData.setCreateTime(format);
            }
            if (tempData[8]!=null) {
                thriftData.setStatus(Integer.valueOf("" + tempData[8]));
            }
            logger.info("[RecordColServiceImpl][getRecordCol][finish][tempData={}]", tempData[0]);
        } catch (Exception e) {
            logger.info("[RecordColServiceImpl][getRecordCol][error][tempData={}][Exception={}]", tempData[0], e);
        }
        return thriftData;
    }


    @Override
    public boolean deleteRecordCol(long id) {
        logger.info("[RecordColServiceImpl][deleteRecordCol][start][id={}]", id);
        try {
            logger.info("[RecordColServiceImpl][deleteRecordCol][finish][id={}]", id);
            RecordCol recordCol = recordColDao.get(id);
            recordCol.setStatus(0);
            recordColDao.save(recordCol);
            return true;
        } catch (Exception e) {
            logger.info("[RecordColServiceImpl][deleteRecordCol][error][id={}]", id);
            return false;
        }
    }

    @Override
    public TRecordColData recordColInfo(long id) {
        logger.info("[RecordColServiceImpl][recordColInfo][start][id={}]", id);
        JSONObject json = null;
        RecordCol recordCol = null;
        try {
            logger.info("[RecordColServiceImpl][recordColInfo][finish][id={}]", id);
            recordCol = recordColDao.get(id);
        } catch (Exception e) {
            logger.info("[RecordColServiceImpl][recordColInfo][error][id={}]", id);
        }
        return transToThrift(recordCol);
    }

    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public List<RecordCol> getRecordColListByChannelId(long id) {

        try {
            String hql = "from RecordCol where channelId ="+id;
            return recordColDao.getSession().createQuery(hql).list();
        } catch (Exception e) {
            logger.error("[RecordColServiceImpl][getRecordColListByChannelId][error]", e);
            return null;
        }
    }

    private TRecordColData transToThrift(RecordCol tempData) {
        TRecordColData thriftData = new TRecordColData();
        try {
            logger.info("[RecordColServiceImpl][getRecordCol][start][tempData={}]", tempData.getId());
            thriftData.setId(tempData.getId());
            thriftData.setCategoryId(tempData.getCategoryId());
            thriftData.setColName(tempData.getColName());
            thriftData.setChannelId(tempData.getChannelId());
            String format = sdf.format(tempData.getCreateTime());
            thriftData.setCreateTime(format);
            thriftData.setOpUser(tempData.getOpUser());
            thriftData.setHasAuth(tempData.getHasAuth());
            thriftData.setHasPublic(tempData.getHasPublic());
            thriftData.setStatus(tempData.getStatus());
            thriftData.setCategoryId(tempData.getCategoryId());
            thriftData.setChannelName(tempData.getChannelName());
            logger.info("[RecordColServiceImpl][getRecordCol][finish][tempData={}]", tempData.getId());
        } catch (Exception e) {
            logger.info("[RecordColServiceImpl][getRecordCol][error][tempData={}][Exception={}]", tempData.getId(), e);
        }
        return thriftData;
    }

}
